<!doctype html>
<html lang="zh"><head>
<title>浏览器-跨域及其解决方案 - 糖羽仙</title>
<meta charset="UTF-8">
<meta name="keywords" content="blog ACG JavaScript VUE IT">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5">

<link rel="shortcut icon" href="/images/head/head.jpg" type="image/jpeg" />
<meta name="description" content="跨域是指一个域下的文档或脚本试图去请求另一个域下的资源">
<meta property="og:type" content="article">
<meta property="og:title" content="浏览器-跨域及其解决方案">
<meta property="og:url" content="https://www.tangyuxian.com/2021/03/19/%E5%89%8D%E7%AB%AF/%E6%B5%8F%E8%A7%88%E5%99%A8/%E6%B5%8F%E8%A7%88%E5%99%A8-%E8%B7%A8%E5%9F%9F%E5%8F%8A%E5%85%B6%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88/index.html">
<meta property="og:site_name" content="糖羽仙">
<meta property="og:description" content="跨域是指一个域下的文档或脚本试图去请求另一个域下的资源">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2021-03-19T06:15:28.000Z">
<meta property="article:modified_time" content="2022-08-20T10:06:06.034Z">
<meta property="article:author" content="tangyuxian">
<meta property="article:tag" content="浏览器">
<meta name="twitter:card" content="summary">

<link rel="stylesheet" href="/lib/fancybox/fancybox.css">
<link rel="stylesheet" href="/lib/mdui_043tiny/mdui.css">


<link rel="stylesheet" href="/lib/iconfont/iconfont.css?v=1763992124176">

    <link rel="stylesheet" href="//at.alicdn.com/t/font_2421060_8z08qcz5sq3.css">

<link rel="stylesheet" href="/css/style.css?v=1763992124176">




    
        <link rel="stylesheet" href="/custom.css?v=1763992124176">
    
        <link rel="stylesheet" href="/themes/umaru/index.css?v=1763992124176">
    
        <link rel="stylesheet" href="/themes/asuka/index.css?v=1763992124176">
    



<script src="/lib/mdui_043tiny/mdui.js" async></script>
<script src="/lib/fancybox/fancybox.umd.js" async></script>
<script src="/lib/lax.min.js" async></script>


<script async src="/js/app.js?v=1763992124176"></script>

 

<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-1Z7TFL96ZH"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'G-1Z7TFL96ZH');
</script>


<link rel="stylesheet"  href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/atom-one-dark.min.css">
<!-- hexo injector head_end start -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/hexo-shiki-plugin@latest/lib/codeblock.css">
<style>:root{--hl-color:#e1e4e8;--hl-bg:#24292e;--hltools-bg:#1f2428;--hltools-color:#c5c5c5;--hlnumber-bg:#24292e;--hlnumber-color:#444d56;--hlscrollbar-bg:#32383e;--hlexpand-bg:linear-gradient(180deg,rgba(36,41,46,0.1),rgba(36,41,46,0.9))}</style><!-- hexo injector head_end end --><meta name="generator" content="Hexo 7.3.0"></head><body class="nexmoe mdui-drawer-body-left"><div id="nexmoe-background"><div class="nexmoe-bg" style="background-image: url(/images/background/xiaomai.jpg)"></div><div class="nexmoe-character"></div><div class="mdui-appbar mdui-shadow-0"><div class="mdui-toolbar"><a class="mdui-btn mdui-btn-icon mdui-ripple" mdui-drawer="{target: &#039;#drawer&#039;, swipe: true}" title="menu"><i class="mdui-icon nexmoefont icon-menu"></i></a><div class="mdui-toolbar-spacer"></div><a class="mdui-btn mdui-btn-icon" href="/" title="tangyuxian"><img src="/images/head/head.jpg" alt="tangyuxian"></a></div></div></div><div id="nexmoe-header"><div class="nexmoe-drawer mdui-drawer" id="drawer">
    <div class="nexmoe-avatar mdui-ripple">
        <a href="/" title="tangyuxian">
            <img src="/images/head/head.jpg" alt="tangyuxian" alt="tangyuxian">
        </a>
    </div>
    <div class="nexmoe-count">
        <div class="nexmoe-count-item"><span>文章</span>84 <div class="item-radius"></div><div class="item-radius item-right"></div> </div>
        <div class="nexmoe-count-item"><span>标签</span>38<div class="item-radius"></div><div class="item-radius item-right"></div></div>
        <div class="nexmoe-count-item"><span>分类</span>5<div class="item-radius"></div><div class="item-radius item-right"></div></div>
    </div>
    <div class="nexmoe-list mdui-list" mdui-collapse="{accordion: true}">
        
        <a class="nexmoe-list-item mdui-list-item mdui-ripple false" href="/" title="回到首页">
            <i class="mdui-list-item-icon nexmoefont icon-meishi"></i>
            <div class="mdui-list-item-content">
                回到首页
            </div>
        </a>
        
        <a class="nexmoe-list-item mdui-list-item mdui-ripple false" href="/archives.html" title="文章归档">
            <i class="mdui-list-item-icon nexmoefont icon-hanbao1"></i>
            <div class="mdui-list-item-content">
                文章归档
            </div>
        </a>
        
        <a class="nexmoe-list-item mdui-list-item mdui-ripple false" href="/about.html" title="关于糖糖">
            <i class="mdui-list-item-icon nexmoefont icon-jiubei1"></i>
            <div class="mdui-list-item-content">
                关于糖糖
            </div>
        </a>
        
        <a class="nexmoe-list-item mdui-list-item mdui-ripple false" href="/friend.html" title="我的朋友">
            <i class="mdui-list-item-icon nexmoefont icon-cola"></i>
            <div class="mdui-list-item-content">
                我的朋友
            </div>
        </a>
        
    </div>
    
    
        
        <div class="nexmoe-widget-wrap">
    <div class="nexmoe-widget nexmoe-search">
         
            <form id="search_form" action_e="https://cn.bing.com/search?q=site:tangyuxian.com" onsubmit="return search();">
                <label><input id="search_value" name="q" type="search" placeholder="搜索"></label>
            </form>
         
    </div>
</div>




    
        
        <div class="nexmoe-widget-wrap">
	<div class="nexmoe-widget nexmoe-social">
		<a
			class="mdui-ripple"
			href="http://wpa.qq.com/msgrd?v=3&uin=2120252100&site=qq&menu=yes"
			target="_blank"
			mdui-tooltip="{content: 'QQ'}"
			style="
				color: rgb(64, 196, 255);
				background-color: rgba(64, 196, 255, .1);
			"
		>
			<i
				class="nexmoefont icon-QQ"
			></i> </a
		><a
			class="mdui-ripple"
			href="mailto:tangyuxian@vip.qq.com"
			target="_blank"
			mdui-tooltip="{content: 'mail'}"
			style="
				color: rgb(249,8,8);
				background-color: rgba(249,8,8,.1);
			"
		>
			<i
				class="nexmoefont icon-mail-fill"
			></i> </a
		><a
			class="mdui-ripple"
			href="https://blog.csdn.net/qq_40621378?type=blog"
			target="_blank"
			mdui-tooltip="{content: 'CSDN'}"
			style="
				color: rgb(199,29,35);
				background-color: rgba(199,29,35,.1);
			"
		>
			<i
				class="nexmoefont icon-csdn"
			></i> </a
		><a
			class="mdui-ripple"
			href="https://www.cnblogs.com/lovetangyuxian/"
			target="_blank"
			mdui-tooltip="{content: '博客园'}"
			style="
				color: rgb(66, 214, 29);
				background-color: rgba(66, 214, 29, .1);
			"
		>
			<i
				class="nexmoefont icon-bokeyuan"
			></i> </a
		><a
			class="mdui-ripple"
			href="https://github.com/tangyuxian/"
			target="_blank"
			mdui-tooltip="{content: 'GitHub'}"
			style="
				color: rgb(25, 23, 23);
				background-color: rgba(25, 23, 23, .15);
			"
		>
			<i
				class="nexmoefont icon-github"
			></i> </a
		><a
			class="mdui-ripple"
			href="https://gitee.com/tangyuxian"
			target="_blank"
			mdui-tooltip="{content: 'gitee'}"
			style="
				color: rgb(255, 255, 255);
				background-color: rgb(199,29,35);
			"
		>
			<i
				class="nexmoefont icon-mayun"
			></i> </a
		>
	</div>
</div>

    
        
        
  <div class="nexmoe-widget-wrap">
    <h3 class="nexmoe-widget-title">文章分类</h3>
    <div class="nexmoe-widget">

      <ul class="category-list">

        


        

        

        <li class="category-list-item">
          <a class="category-list-link" href="/categories/其它/">其它</a>
          <span class="category-list-count">2</span>
        </li>

        

        <li class="category-list-item">
          <a class="category-list-link" href="/categories/前端/">前端</a>
          <span class="category-list-count">62</span>
        </li>

        

        <li class="category-list-item">
          <a class="category-list-link" href="/categories/后端/">后端</a>
          <span class="category-list-count">8</span>
        </li>

        

        <li class="category-list-item">
          <a class="category-list-link" href="/categories/开发工具/">开发工具</a>
          <span class="category-list-count">11</span>
        </li>

        

        <li class="category-list-item">
          <a class="category-list-link" href="/categories/服务器端/">服务器端</a>
          <span class="category-list-count">1</span>
        </li>

        
      </ul>

    </div>
  </div>


    
        
        
  <div class="nexmoe-widget-wrap">
    <div id="randomtagcloud" class="nexmoe-widget tagcloud nexmoe-rainbow">
      <a href="/tags/JavaScript/" style="font-size: 15.56px;">JavaScript</a> <a href="/tags/Jetbrains/" style="font-size: 10px;">Jetbrains</a> <a href="/tags/TypeScript/" style="font-size: 10px;">TypeScript</a> <a href="/tags/UI%E5%BA%93/" style="font-size: 13.33px;">UI库</a> <a href="/tags/centos/" style="font-size: 10px;">centos</a> <a href="/tags/css/" style="font-size: 11.11px;">css</a> <a href="/tags/docker/" style="font-size: 10px;">docker</a> <a href="/tags/echarts/" style="font-size: 10px;">echarts</a> <a href="/tags/elementPlus/" style="font-size: 13.33px;">elementPlus</a> <a href="/tags/es6/" style="font-size: 14.44px;">es6</a> <a href="/tags/git/" style="font-size: 13.33px;">git</a> <a href="/tags/github/" style="font-size: 10px;">github</a> <a href="/tags/html/" style="font-size: 10px;">html</a> <a href="/tags/http/" style="font-size: 13.33px;">http</a> <a href="/tags/java/" style="font-size: 11.11px;">java</a> <a href="/tags/markerdown/" style="font-size: 11.11px;">markerdown</a> <a href="/tags/nginx/" style="font-size: 10px;">nginx</a> <a href="/tags/node/" style="font-size: 13.33px;">node</a> <a href="/tags/vite/" style="font-size: 10px;">vite</a> <a href="/tags/vue/" style="font-size: 18.89px;">vue</a> <a href="/tags/webpack/" style="font-size: 10px;">webpack</a> <a href="/tags/xuex/" style="font-size: 10px;">xuex</a> <a href="/tags/%E4%BA%8B%E4%BB%B6%E6%B5%81/" style="font-size: 10px;">事件流</a> <a href="/tags/%E4%BA%92%E8%81%94%E7%BD%91/" style="font-size: 10px;">互联网</a> <a href="/tags/%E5%8A%A0%E5%AF%86/" style="font-size: 12.22px;">加密</a> <a href="/tags/%E5%8E%9F%E5%88%9B/" style="font-size: 20px;">原创</a> <a href="/tags/%E5%B7%A5%E5%85%B7/" style="font-size: 13.33px;">工具</a> <a href="/tags/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F/" style="font-size: 12.22px;">微信小程序</a> <a href="/tags/%E6%80%BB%E7%BB%93/" style="font-size: 13.33px;">总结</a> <a href="/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/" style="font-size: 10px;">数据结构</a> <a href="/tags/%E6%9C%8D%E5%8A%A1%E5%99%A8/" style="font-size: 10px;">服务器</a> <a href="/tags/%E6%B5%8F%E8%A7%88%E5%99%A8/" style="font-size: 17.78px;">浏览器</a> <a href="/tags/%E7%AE%97%E6%B3%95/" style="font-size: 14.44px;">算法</a> <a href="/tags/%E7%BC%96%E8%A7%A3%E7%A0%81/" style="font-size: 10px;">编解码</a> <a href="/tags/%E7%BE%8E%E5%8C%96/" style="font-size: 12.22px;">美化</a> <a href="/tags/%E8%A7%86%E9%A2%91/" style="font-size: 11.11px;">视频</a> <a href="/tags/%E8%AE%B0%E5%BD%95/" style="font-size: 11.11px;">记录</a> <a href="/tags/%E8%BD%AC%E8%BD%BD/" style="font-size: 16.67px;">转载</a>
    </div>
    
      <script>
        var maxTagcloud = parseInt(17);
        var tags_length = parseInt(38);
        var tags_arr = [];
        for(var i = 0; i < tags_length; i++){
          tags_arr.push(i);
        }
        tags_arr.sort(function (l, r) {
          return Math.random() > 0.5 ? -1 : 1;
        });
        tags_arr = tags_arr.slice(0, maxTagcloud < tags_length ? tags_length - maxTagcloud : 0);
        for(var tag_i = 0; tag_i < tags_arr.length; tag_i++){
          document.getElementById("randomtagcloud").children[tags_arr[tag_i]].style.display = 'none';
        }
      </script>
    
  </div>

    
        
        
        
  <div class="nexmoe-widget-wrap">
    <h3 class="nexmoe-widget-title">文章归档</h3>
    <div class="nexmoe-widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2025/">2025</a><span class="archive-list-count">5</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2023/">2023</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2022/">2022</a><span class="archive-list-count">23</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2021/">2021</a><span class="archive-list-count">54</span></li></ul>
    </div>
  </div>



    
        
        
  <div class="nexmoe-widget-wrap">
    <h3 class="nexmoe-widget-title">最新文章</h3>
    <div class="nexmoe-widget">
      <ul>
        
          <li>
            <a href="/2025/11/12/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/%E7%BE%8E%E5%8C%96/%E7%BE%8E%E5%8C%96-%E7%BD%91%E9%A1%B5%E4%B8%BB%E9%A2%98%E5%88%87%E6%8D%A2%E7%9A%84%E6%B8%90%E5%8F%98%E5%8A%A8%E7%94%BB/">美化-网页主题切换的渐变动画</a>
          </li>
        
          <li>
            <a href="/2025/09/29/%E5%89%8D%E7%AB%AF/css/css-%E8%A1%A8%E6%A0%BCtd%E4%B8%8B%E9%AB%98%E5%BA%A6%E4%B8%A2%E5%A4%B1%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95/">css-表格td下高度丢失解决办法</a>
          </li>
        
          <li>
            <a href="/2025/09/23/%E5%89%8D%E7%AB%AF/vue/vue-%E5%B0%81%E8%A3%85%E5%87%BD%E6%95%B0%E5%BC%8F%E8%A7%A6%E5%8F%91%E5%8F%B3%E9%94%AE%E8%8F%9C%E5%8D%95/">vue-封装函数式触发右键菜单组件</a>
          </li>
        
          <li>
            <a href="/2025/06/04/%E5%89%8D%E7%AB%AF/UI%E5%BA%93/UI%E5%BA%93-ElTooltip%E5%8F%AA%E5%9C%A8%E6%96%87%E5%AD%97%E8%B6%85%E5%87%BA%E8%8C%83%E5%9B%B4%E6%97%B6%E6%98%BE%E7%A4%BA%E7%9A%84%E8%A7%86%E7%BA%BF%E6%96%B9%E5%BC%8F/">UI库-ElTooltip只在文字超出范围时显示的视线方式</a>
          </li>
        
          <li>
            <a href="/2025/05/29/%E5%89%8D%E7%AB%AF/UI%E5%BA%93/UI%E5%BA%93-%E5%B0%81%E8%A3%85PageTable%E6%80%BB%E8%A7%88/">UI库-封装PageTable总览</a>
          </li>
        
      </ul>
    </div>
  </div>

    
        
        <div class="nexmoe-widget-wrap">
    <div class="nexmoe-widget nexmoe-link">
		<ul>
        
            <li>
                <a href="https://tangyuxian.com/" target="_blank" >
                    <img src="https://cdn.tangyuxian.com/PicGoImages/202304272004917.jpg" alt="糖糖第一可爱"></img>
                    <p style="color: var(--color-primary)">糖糖第一可爱</p>
                </a>
            </li>
        
		</ul>
    </div>
</div>
<style>
.nexmoe-widget-wrap .nexmoe-link ul li a {
    text-align : center;
}
.nexmoe-widget-wrap .nexmoe-link ul li a img {
    max-width : 100%;
}
.nexmoe-widget-wrap .nexmoe-link ul li a p {
    margin: 10px 0;
}
</style>

    
   
    <div class="nexmoe-copyright">
        &copy; 2025 tangyuxian
        Powered by <a href="http://hexo.io/" target="_blank">Hexo</a>
        & <a href="https://github.com/tangyuxian/hexo-theme-tangyuxian" target="_blank">Tangyuxian</a>
        <br><a target="_blank" href="https://beian.miit.gov.cn/">辽ICP备2021002341号</a>
<div style="font-size: 12px">
   <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
   本站总访问量  <a id="busuanzi_value_site_pv"></a> 次<br />
   本站访客数<a id="busuanzi_value_site_uv"></a>人次
</div>

    </div>
</div><!-- .nexmoe-drawer --></div><div id="nexmoe-content"><div class="nexmoe-primary"><div class="nexmoe-post">
  <article>
    
        <div class="nexmoe-post-cover">
            <img src="/images/post/browser.jpg" alt="浏览器-跨域及其解决方案" loading="lazy">
            <h1>浏览器-跨域及其解决方案</h1>
        </div>
        
    
    <div class="nexmoe-post-meta">
    <div class="nexmoe-rainbow">
        <a class="nexmoefont icon-calendar-fill">2021年03月19日</a>
        
            <a class="nexmoefont icon-appstore-fill -link" href="/categories/%E5%89%8D%E7%AB%AF/">前端</a>
        
        
    </div>
    
    
    
    
    
</div>

    <p>跨域是指一个域下的文档或脚本试图去请求另一个域下的资源</p>
<span id="more"></span>

<h2 id="什么是跨域？"><a href="#什么是跨域？" class="headerlink" title="什么是跨域？"></a><strong>什么是跨域？</strong></h2><p>跨域是指一个域下的文档或脚本试图去请求另一个域下的资源，这里跨域是广义的。</p>
<p>广义的跨域：</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">1.) 资源跳转： A链接、重定向、表单提交</span></span>
<span class="line"><span style="color: #e1e4e8">2.) 资源嵌入： &lt;link&gt;、&lt;script&gt;、&lt;img&gt;、&lt;frame&gt;等dom标签，还有样式中background:url()、@font-face()等文件外链</span></span>
<span class="line"><span style="color: #e1e4e8">3.) 脚本请求： js发起的ajax请求、dom和js对象的跨域操作等</span></span></code></pre></div></div></figure>

<p>其实我们通常所说的跨域是狭义的，是由浏览器同源策略限制的一类请求场景。</p>
<p><strong>什么是同源策略？</strong><br>同源策略&#x2F;SOP（Same origin policy）是一种约定，由Netscape公司1995年引入浏览器，它是浏览器最核心也最基本的安全功能，如果缺少了同源策略，浏览器很容易受到XSS、CSFR等攻击。所谓同源是指”协议+域名+端口”三者相同，即便两个不同的域名指向同一个ip地址，也非同源。</p>
<p>同源策略限制以下几种行为：</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">1.) Cookie、LocalStorage 和 IndexDB 无法读取</span></span>
<span class="line"><span style="color: #e1e4e8">2.) DOM 和 Js对象无法获得</span></span>
<span class="line"><span style="color: #e1e4e8">3.) AJAX 请求不能发送</span></span></code></pre></div></div></figure>

<h2 id="常见跨域场景"><a href="#常见跨域场景" class="headerlink" title="常见跨域场景"></a><strong>常见跨域场景</strong></h2><figure class="shiki text"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">URL                                      说明                    是否允许通信</span></span>
<span class="line"><span style="color: #e1e4e8">http://www.domain.com/a.js</span></span>
<span class="line"><span style="color: #e1e4e8">http://www.domain.com/b.js         同一域名，不同文件或路径           允许</span></span>
<span class="line"><span style="color: #e1e4e8">http://www.domain.com/lab/c.js</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">http://www.domain.com:8000/a.js</span></span>
<span class="line"><span style="color: #e1e4e8">http://www.domain.com/b.js         同一域名，不同端口                不允许</span></span>
<span class="line"><span style="color: #e1e4e8"> </span></span>
<span class="line"><span style="color: #e1e4e8">http://www.domain.com/a.js</span></span>
<span class="line"><span style="color: #e1e4e8">https://www.domain.com/b.js        同一域名，不同协议                不允许</span></span>
<span class="line"><span style="color: #e1e4e8"> </span></span>
<span class="line"><span style="color: #e1e4e8">http://www.domain.com/a.js</span></span>
<span class="line"><span style="color: #e1e4e8">http://192.168.4.12/b.js           域名和域名对应相同ip              不允许</span></span>
<span class="line"><span style="color: #e1e4e8"> </span></span>
<span class="line"><span style="color: #e1e4e8">http://www.domain.com/a.js</span></span>
<span class="line"><span style="color: #e1e4e8">http://x.domain.com/b.js           主域相同，子域不同                不允许</span></span>
<span class="line"><span style="color: #e1e4e8">http://domain.com/c.js</span></span>
<span class="line"><span style="color: #e1e4e8"> </span></span>
<span class="line"><span style="color: #e1e4e8">http://www.domain1.com/a.js</span></span>
<span class="line"><span style="color: #e1e4e8">http://www.domain2.com/b.js        不同域名                         不允许</span></span></code></pre></div></div></figure>

<h2 id="跨域解决方案"><a href="#跨域解决方案" class="headerlink" title="跨域解决方案"></a><strong>跨域解决方案</strong></h2><p>1、 通过jsonp跨域<br>2、 document.domain + iframe跨域<br>3、 location.hash + iframe<br>4、 window.name + iframe跨域<br>5、 postMessage跨域<br>6、 跨域资源共享（CORS）<br>7、 nginx代理跨域<br>8、 nodejs中间件代理跨域<br>9、 WebSocket协议跨域</p>
<h4 id="一、-通过jsonp跨域"><a href="#一、-通过jsonp跨域" class="headerlink" title="一、 通过jsonp跨域"></a><strong>一、 通过jsonp跨域</strong></h4><p>通常为了减轻web服务器的负载，我们把js、css，img等静态资源分离到另一台独立域名的服务器上，在html页面中再通过相应的标签从不同域名下加载静态资源，而被浏览器允许，基于此原理，我们可以通过动态创建script，再请求一个带参网址实现跨域通信。</p>
<p>1.）原生实现：</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">&lt;script&gt;</span></span>
<span class="line"><span style="color: #e1e4e8">   var script = document.createElement(&#39;script&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8">   script.type = &#39;text/javascript&#39;;</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">   // 传参一个回调函数名给后端，方便后端返回时执行这个在前端定义的回调函数</span></span>
<span class="line"><span style="color: #e1e4e8">   script.src = &#39;http://www.domain2.com:8080/login?user=admin&amp;callback=handleCallback&#39;;</span></span>
<span class="line"><span style="color: #e1e4e8">   document.head.appendChild(script);</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">   // 回调执行函数</span></span>
<span class="line"><span style="color: #e1e4e8">   function handleCallback(res) {</span></span>
<span class="line"><span style="color: #e1e4e8">       alert(JSON.stringify(res));</span></span>
<span class="line"><span style="color: #e1e4e8">   }</span></span>
<span class="line"><span style="color: #e1e4e8">&lt;/script&gt;</span></span></code></pre></div></div></figure>

<p>服务端返回如下（返回时即执行全局函数）：</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">handleCallback({&quot;status&quot;: true, &quot;user&quot;: &quot;admin&quot;})</span></span></code></pre></div></div></figure>

<p>2.）jquery ajax：</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">$.ajax({</span></span>
<span class="line"><span style="color: #e1e4e8">    url: &#39;http://www.domain2.com:8080/login&#39;,</span></span>
<span class="line"><span style="color: #e1e4e8">    type: &#39;get&#39;,</span></span>
<span class="line"><span style="color: #e1e4e8">    dataType: &#39;jsonp&#39;,  // 请求方式为jsonp</span></span>
<span class="line"><span style="color: #e1e4e8">    jsonpCallback: &quot;handleCallback&quot;,    // 自定义回调函数名</span></span>
<span class="line"><span style="color: #e1e4e8">    data: {}</span></span>
<span class="line"><span style="color: #e1e4e8">});</span></span></code></pre></div></div></figure>

<p>3.）vue.js：</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">this.$http.jsonp(&#39;http://www.domain2.com:8080/login&#39;, {</span></span>
<span class="line"><span style="color: #e1e4e8">    params: {},</span></span>
<span class="line"><span style="color: #e1e4e8">    jsonp: &#39;handleCallback&#39;</span></span>
<span class="line"><span style="color: #e1e4e8">}).then((res) =&gt; {</span></span>
<span class="line"><span style="color: #e1e4e8">    console.log(res); </span></span>
<span class="line"><span style="color: #e1e4e8">})</span></span></code></pre></div></div></figure>

<p>后端node.js代码示例：</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">var querystring = require(&#39;querystring&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8">var http = require(&#39;http&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8">var server = http.createServer();</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">server.on(&#39;request&#39;, function(req, res) {</span></span>
<span class="line"><span style="color: #e1e4e8">    var params = qs.parse(req.url.split(&#39;?&#39;)[1]);</span></span>
<span class="line"><span style="color: #e1e4e8">    var fn = params.callback;</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">    // jsonp返回设置</span></span>
<span class="line"><span style="color: #e1e4e8">    res.writeHead(200, { &#39;Content-Type&#39;: &#39;text/javascript&#39; });</span></span>
<span class="line"><span style="color: #e1e4e8">    res.write(fn + &#39;(&#39; + JSON.stringify(params) + &#39;)&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">    res.end();</span></span>
<span class="line"><span style="color: #e1e4e8">});</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">server.listen(&#39;8080&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8">console.log(&#39;Server is running at port 8080...&#39;);</span></span></code></pre></div></div></figure>

<p>jsonp缺点：只能实现get一种请求。</p>
<h4 id="二、-document-domain-iframe跨域"><a href="#二、-document-domain-iframe跨域" class="headerlink" title="二、 document.domain + iframe跨域"></a><strong>二、 document.domain + iframe跨域</strong></h4><p>此方案仅限主域相同，子域不同的跨域应用场景。</p>
<p>实现原理：两个页面都通过js强制设置document.domain为基础主域，就实现了同域。</p>
<p>1.）父窗口：(<a target="_blank" rel="noopener" href="http://www.domain.com/a.html">http://www.domain.com/a.html</a>)</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">&lt;iframe id=&quot;iframe&quot; src=&quot;http://child.domain.com/b.html&quot;&gt;&lt;/iframe&gt;</span></span>
<span class="line"><span style="color: #e1e4e8">&lt;script&gt;</span></span>
<span class="line"><span style="color: #e1e4e8">    document.domain = &#39;domain.com&#39;;</span></span>
<span class="line"><span style="color: #e1e4e8">    var user = &#39;admin&#39;;</span></span>
<span class="line"><span style="color: #e1e4e8">&lt;/script&gt;</span></span></code></pre></div></div></figure>

<p>2.）子窗口：(<a target="_blank" rel="noopener" href="http://child.domain.com/b.html">http://child.domain.com/b.html</a>)</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">&lt;script&gt;</span></span>
<span class="line"><span style="color: #e1e4e8">    document.domain = &#39;domain.com&#39;;</span></span>
<span class="line"><span style="color: #e1e4e8">    // 获取父窗口中变量</span></span>
<span class="line"><span style="color: #e1e4e8">    alert(&#39;get js data from parent ---&gt; &#39; + window.parent.user);</span></span>
<span class="line"><span style="color: #e1e4e8">&lt;/script&gt;</span></span></code></pre></div></div></figure>

<h4 id="三、-location-hash-iframe跨域"><a href="#三、-location-hash-iframe跨域" class="headerlink" title="三、 location.hash + iframe跨域"></a><strong>三、 location.hash + iframe跨域</strong></h4><p>实现原理： a欲与b跨域相互通信，通过中间页c来实现。 三个页面，不同域之间利用iframe的location.hash传值，相同域之间直接js访问来通信。</p>
<p>具体实现：A域：a.html -&gt; B域：b.html -&gt; A域：c.html，a与b不同域只能通过hash值单向通信，b与c也不同域也只能单向通信，但c与a同域，所以c可通过parent.parent访问a页面所有对象。</p>
<p>1.）a.html：(<a target="_blank" rel="noopener" href="http://www.domain1.com/a.html">http://www.domain1.com/a.html</a>)</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">&lt;iframe id=&quot;iframe&quot; src=&quot;http://www.domain2.com/b.html&quot; style=&quot;display:none;&quot;&gt;&lt;/iframe&gt;</span></span>
<span class="line"><span style="color: #e1e4e8">&lt;script&gt;</span></span>
<span class="line"><span style="color: #e1e4e8">    var iframe = document.getElementById(&#39;iframe&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">    // 向b.html传hash值</span></span>
<span class="line"><span style="color: #e1e4e8">    setTimeout(function() {</span></span>
<span class="line"><span style="color: #e1e4e8">        iframe.src = iframe.src + &#39;#user=admin&#39;;</span></span>
<span class="line"><span style="color: #e1e4e8">    }, 1000);</span></span>
<span class="line"><span style="color: #e1e4e8">    </span></span>
<span class="line"><span style="color: #e1e4e8">    // 开放给同域c.html的回调方法</span></span>
<span class="line"><span style="color: #e1e4e8">    function onCallback(res) {</span></span>
<span class="line"><span style="color: #e1e4e8">        alert(&#39;data from c.html ---&gt; &#39; + res);</span></span>
<span class="line"><span style="color: #e1e4e8">    }</span></span>
<span class="line"><span style="color: #e1e4e8">&lt;/script&gt;</span></span></code></pre></div></div></figure>

<p>2.）b.html：(<a target="_blank" rel="noopener" href="http://www.domain2.com/b.html">http://www.domain2.com/b.html</a>)</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">&lt;iframe id=&quot;iframe&quot; src=&quot;http://www.domain1.com/c.html&quot; style=&quot;display:none;&quot;&gt;&lt;/iframe&gt;</span></span>
<span class="line"><span style="color: #e1e4e8">&lt;script&gt;</span></span>
<span class="line"><span style="color: #e1e4e8">    var iframe = document.getElementById(&#39;iframe&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">    // 监听a.html传来的hash值，再传给c.html</span></span>
<span class="line"><span style="color: #e1e4e8">    window.onhashchange = function () {</span></span>
<span class="line"><span style="color: #e1e4e8">        iframe.src = iframe.src + location.hash;</span></span>
<span class="line"><span style="color: #e1e4e8">    };</span></span>
<span class="line"><span style="color: #e1e4e8">&lt;/script&gt;</span></span></code></pre></div></div></figure>

<p>3.）c.html：(<a target="_blank" rel="noopener" href="http://www.domain1.com/c.html">http://www.domain1.com/c.html</a>)</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">&lt;script&gt;</span></span>
<span class="line"><span style="color: #e1e4e8">    // 监听b.html传来的hash值</span></span>
<span class="line"><span style="color: #e1e4e8">    window.onhashchange = function () {</span></span>
<span class="line"><span style="color: #e1e4e8">        // 再通过操作同域a.html的js回调，将结果传回</span></span>
<span class="line"><span style="color: #e1e4e8">        window.parent.parent.onCallback(&#39;hello: &#39; + location.hash.replace(&#39;#user=&#39;, &#39;&#39;));</span></span>
<span class="line"><span style="color: #e1e4e8">    };</span></span>
<span class="line"><span style="color: #e1e4e8">&lt;/script&gt;</span></span></code></pre></div></div></figure>

<h4 id="四、-window-name-iframe跨域"><a href="#四、-window-name-iframe跨域" class="headerlink" title="四、 window.name + iframe跨域"></a><strong>四、 window.name + iframe跨域</strong></h4><p>window.name属性的独特之处：name值在不同的页面（甚至不同域名）加载后依旧存在，并且可以支持非常长的 name 值（2MB）。</p>
<p>1.）a.html：(<a target="_blank" rel="noopener" href="http://www.domain1.com/a.html">http://www.domain1.com/a.html</a>)</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">var proxy = function(url, callback) {</span></span>
<span class="line"><span style="color: #e1e4e8">    var state = 0;</span></span>
<span class="line"><span style="color: #e1e4e8">    var iframe = document.createElement(&#39;iframe&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">    // 加载跨域页面</span></span>
<span class="line"><span style="color: #e1e4e8">    iframe.src = url;</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">    // onload事件会触发2次，第1次加载跨域页，并留存数据于window.name</span></span>
<span class="line"><span style="color: #e1e4e8">    iframe.onload = function() {</span></span>
<span class="line"><span style="color: #e1e4e8">        if (state === 1) {</span></span>
<span class="line"><span style="color: #e1e4e8">            // 第2次onload(同域proxy页)成功后，读取同域window.name中数据</span></span>
<span class="line"><span style="color: #e1e4e8">            callback(iframe.contentWindow.name);</span></span>
<span class="line"><span style="color: #e1e4e8">            destoryFrame();</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">        } else if (state === 0) {</span></span>
<span class="line"><span style="color: #e1e4e8">            // 第1次onload(跨域页)成功后，切换到同域代理页面</span></span>
<span class="line"><span style="color: #e1e4e8">            iframe.contentWindow.location = &#39;http://www.domain1.com/proxy.html&#39;;</span></span>
<span class="line"><span style="color: #e1e4e8">            state = 1;</span></span>
<span class="line"><span style="color: #e1e4e8">        }</span></span>
<span class="line"><span style="color: #e1e4e8">    };</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">    document.body.appendChild(iframe);</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">    // 获取数据以后销毁这个iframe，释放内存；这也保证了安全（不被其他域frame js访问）</span></span>
<span class="line"><span style="color: #e1e4e8">    function destoryFrame() {</span></span>
<span class="line"><span style="color: #e1e4e8">        iframe.contentWindow.document.write(&#39;&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8">        iframe.contentWindow.close();</span></span>
<span class="line"><span style="color: #e1e4e8">        document.body.removeChild(iframe);</span></span>
<span class="line"><span style="color: #e1e4e8">    }</span></span>
<span class="line"><span style="color: #e1e4e8">};</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">// 请求跨域b页面数据</span></span>
<span class="line"><span style="color: #e1e4e8">proxy(&#39;http://www.domain2.com/b.html&#39;, function(data){</span></span>
<span class="line"><span style="color: #e1e4e8">    alert(data);</span></span>
<span class="line"><span style="color: #e1e4e8">});</span></span></code></pre></div></div></figure>

<p>2.）proxy.html：(<a target="_blank" rel="noopener" href="http://www.domain1.com/proxy.html">http://www.domain1.com/proxy....</a>)<br>中间代理页，与a.html同域，内容为空即可。</p>
<p>3.）b.html：(<a target="_blank" rel="noopener" href="http://www.domain2.com/b.html">http://www.domain2.com/b.html</a>)</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">&lt;script&gt;</span></span>
<span class="line"><span style="color: #e1e4e8">    window.name = &#39;This is domain2 data!&#39;;</span></span>
<span class="line"><span style="color: #e1e4e8">&lt;/script&gt;</span></span></code></pre></div></div></figure>

<p>总结：通过iframe的src属性由外域转向本地域，跨域数据即由iframe的window.name从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制，但同时它又是安全操作。</p>
<h4 id="五、-postMessage跨域"><a href="#五、-postMessage跨域" class="headerlink" title="五、 postMessage跨域"></a><strong>五、 postMessage跨域</strong></h4><p>postMessage是HTML5 XMLHttpRequest Level 2中的API，且是为数不多可以跨域操作的window属性之一，它可用于解决以下方面的问题：<br>a.） 页面和其打开的新窗口的数据传递<br>b.） 多窗口之间消息传递<br>c.） 页面与嵌套的iframe消息传递<br>d.） 上面三个场景的跨域数据传递</p>
<p>用法：postMessage(data,origin)方法接受两个参数<br>data： html5规范支持任意基本类型或可复制的对象，但部分浏览器只支持字符串，所以传参时最好用JSON.stringify()序列化。<br>origin： 协议+主机+端口号，也可以设置为”*”，表示可以传递给任意窗口，如果要指定和当前窗口同源的话设置为”&#x2F;“。</p>
<p>1.）a.html：(<a target="_blank" rel="noopener" href="http://www.domain1.com/a.html">http://www.domain1.com/a.html</a>)</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">&lt;iframe id=&quot;iframe&quot; src=&quot;http://www.domain2.com/b.html&quot; style=&quot;display:none;&quot;&gt;&lt;/iframe&gt;</span></span>
<span class="line"><span style="color: #e1e4e8">&lt;script&gt;       </span></span>
<span class="line"><span style="color: #e1e4e8">    var iframe = document.getElementById(&#39;iframe&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8">    iframe.onload = function() {</span></span>
<span class="line"><span style="color: #e1e4e8">        var data = {</span></span>
<span class="line"><span style="color: #e1e4e8">            name: &#39;aym&#39;</span></span>
<span class="line"><span style="color: #e1e4e8">        };</span></span>
<span class="line"><span style="color: #e1e4e8">        // 向domain2传送跨域数据</span></span>
<span class="line"><span style="color: #e1e4e8">        iframe.contentWindow.postMessage(JSON.stringify(data), &#39;http://www.domain2.com&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8">    };</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">    // 接受domain2返回数据</span></span>
<span class="line"><span style="color: #e1e4e8">    window.addEventListener(&#39;message&#39;, function(e) {</span></span>
<span class="line"><span style="color: #e1e4e8">        alert(&#39;data from domain2 ---&gt; &#39; + e.data);</span></span>
<span class="line"><span style="color: #e1e4e8">    }, false);</span></span>
<span class="line"><span style="color: #e1e4e8">&lt;/script&gt;</span></span></code></pre></div></div></figure>

<p>2.）b.html：(<a target="_blank" rel="noopener" href="http://www.domain2.com/b.html">http://www.domain2.com/b.html</a>)</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">&lt;script&gt;</span></span>
<span class="line"><span style="color: #e1e4e8">    // 接收domain1的数据</span></span>
<span class="line"><span style="color: #e1e4e8">    window.addEventListener(&#39;message&#39;, function(e) {</span></span>
<span class="line"><span style="color: #e1e4e8">        alert(&#39;data from domain1 ---&gt; &#39; + e.data);</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">        var data = JSON.parse(e.data);</span></span>
<span class="line"><span style="color: #e1e4e8">        if (data) {</span></span>
<span class="line"><span style="color: #e1e4e8">            data.number = 16;</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">            // 处理后再发回domain1</span></span>
<span class="line"><span style="color: #e1e4e8">            window.parent.postMessage(JSON.stringify(data), &#39;http://www.domain1.com&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8">        }</span></span>
<span class="line"><span style="color: #e1e4e8">    }, false);</span></span>
<span class="line"><span style="color: #e1e4e8">&lt;/script&gt;</span></span></code></pre></div></div></figure>

<h4 id="六、-跨域资源共享（CORS）"><a href="#六、-跨域资源共享（CORS）" class="headerlink" title="六、 跨域资源共享（CORS）"></a><strong>六、 跨域资源共享（CORS）</strong></h4><p>普通跨域请求：只服务端设置Access-Control-Allow-Origin即可，前端无须设置，若要带cookie请求：前后端都需要设置。</p>
<p>需注意的是：由于同源策略的限制，所读取的cookie为跨域请求接口所在域的cookie，而非当前页。如果想实现当前页cookie的写入，可参考下文：七、nginx反向代理中设置proxy_cookie_domain 和 八、NodeJs中间件代理中cookieDomainRewrite参数的设置。</p>
<p>目前，所有浏览器都支持该功能(IE8+：IE8&#x2F;9需要使用XDomainRequest对象来支持CORS）)，CORS也已经成为主流的跨域解决方案。</p>
<h5 id="1、-前端设置："><a href="#1、-前端设置：" class="headerlink" title="1、 前端设置："></a><strong>1、 前端设置：</strong></h5><p>1.）原生ajax</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">// 前端设置是否带cookie</span></span>
<span class="line"><span style="color: #e1e4e8">xhr.withCredentials = true;</span></span></code></pre></div></div></figure>

<p>示例代码：</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">// 前端设置是否带cookie</span></span>
<span class="line"><span style="color: #e1e4e8">xhr.withCredentials = true;</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">xhr.open(&#39;post&#39;, &#39;http://www.domain2.com:8080/login&#39;, true);</span></span>
<span class="line"><span style="color: #e1e4e8">xhr.setRequestHeader(&#39;Content-Type&#39;, &#39;application/x-www-form-urlencoded&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8">xhr.send(&#39;user=admin&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">xhr.onreadystatechange = function() {</span></span>
<span class="line"><span style="color: #e1e4e8">    if (xhr.readyState == 4 &amp;&amp; xhr.status == 200) {</span></span>
<span class="line"><span style="color: #e1e4e8">        alert(xhr.responseText);</span></span>
<span class="line"><span style="color: #e1e4e8">    }</span></span>
<span class="line"><span style="color: #e1e4e8">};</span></span></code></pre></div></div></figure>

<p>2.）jQuery ajax</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">$.ajax({</span></span>
<span class="line"><span style="color: #e1e4e8">    ...</span></span>
<span class="line"><span style="color: #e1e4e8">   xhrFields: {</span></span>
<span class="line"><span style="color: #e1e4e8">       withCredentials: true    // 前端设置是否带cookie</span></span>
<span class="line"><span style="color: #e1e4e8">   },</span></span>
<span class="line"><span style="color: #e1e4e8">   crossDomain: true,   // 会让请求头中包含跨域的额外信息，但不会含cookie</span></span>
<span class="line"><span style="color: #e1e4e8">    ...</span></span>
<span class="line"><span style="color: #e1e4e8">});</span></span></code></pre></div></div></figure>

<p>3.）vue框架</p>
<p>a.) axios设置：</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">axios.defaults.withCredentials = true</span></span></code></pre></div></div></figure>

<p>b.) vue-resource设置：</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">Vue.http.options.credentials = true</span></span></code></pre></div></div></figure>

<h5 id="2、-服务端设置："><a href="#2、-服务端设置：" class="headerlink" title="2、 服务端设置："></a><strong>2、 服务端设置：</strong></h5><p>若后端设置成功，前端浏览器控制台则不会出现跨域报错信息，反之，说明没设成功。</p>
<p>1.）Java后台：</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">/*</span></span>
<span class="line"><span style="color: #e1e4e8"> * 导入包：import javax.servlet.http.HttpServletResponse;</span></span>
<span class="line"><span style="color: #e1e4e8"> * 接口参数中定义：HttpServletResponse response</span></span>
<span class="line"><span style="color: #e1e4e8"> */</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">// 允许跨域访问的域名：若有端口需写全（协议+域名+端口），若没有端口末尾不用加&#39;/&#39;</span></span>
<span class="line"><span style="color: #e1e4e8">response.setHeader(&quot;Access-Control-Allow-Origin&quot;, &quot;http://www.domain1.com&quot;); </span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">// 允许前端带认证cookie：启用此项后，上面的域名不能为&#39;*&#39;，必须指定具体的域名，否则浏览器会提示</span></span>
<span class="line"><span style="color: #e1e4e8">response.setHeader(&quot;Access-Control-Allow-Credentials&quot;, &quot;true&quot;); </span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">// 提示OPTIONS预检时，后端需要设置的两个常用自定义头</span></span>
<span class="line"><span style="color: #e1e4e8">response.setHeader(&quot;Access-Control-Allow-Headers&quot;, &quot;Content-Type,X-Requested-With&quot;);</span></span></code></pre></div></div></figure>

<p>2.）Nodejs后台示例：</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">var http = require(&#39;http&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8">var server = http.createServer();</span></span>
<span class="line"><span style="color: #e1e4e8">var qs = require(&#39;querystring&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">server.on(&#39;request&#39;, function(req, res) {</span></span>
<span class="line"><span style="color: #e1e4e8">    var postData = &#39;&#39;;</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">    // 数据块接收中</span></span>
<span class="line"><span style="color: #e1e4e8">    req.addListener(&#39;data&#39;, function(chunk) {</span></span>
<span class="line"><span style="color: #e1e4e8">        postData += chunk;</span></span>
<span class="line"><span style="color: #e1e4e8">    });</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">    // 数据接收完毕</span></span>
<span class="line"><span style="color: #e1e4e8">    req.addListener(&#39;end&#39;, function() {</span></span>
<span class="line"><span style="color: #e1e4e8">        postData = qs.parse(postData);</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">        // 跨域后台设置</span></span>
<span class="line"><span style="color: #e1e4e8">        res.writeHead(200, {</span></span>
<span class="line"><span style="color: #e1e4e8">            &#39;Access-Control-Allow-Credentials&#39;: &#39;true&#39;,     // 后端允许发送Cookie</span></span>
<span class="line"><span style="color: #e1e4e8">            &#39;Access-Control-Allow-Origin&#39;: &#39;http://www.domain1.com&#39;,    // 允许访问的域（协议+域名+端口）</span></span>
<span class="line"><span style="color: #e1e4e8">            /* </span></span>
<span class="line"><span style="color: #e1e4e8">             * 此处设置的cookie还是domain2的而非domain1，因为后端也不能跨域写cookie(nginx反向代理可以实现)，</span></span>
<span class="line"><span style="color: #e1e4e8">             * 但只要domain2中写入一次cookie认证，后面的跨域接口都能从domain2中获取cookie，从而实现所有的接口都能跨域访问</span></span>
<span class="line"><span style="color: #e1e4e8">             */</span></span>
<span class="line"><span style="color: #e1e4e8">            &#39;Set-Cookie&#39;: &#39;l=a123456;Path=/;Domain=www.domain2.com;HttpOnly&#39;  // HttpOnly的作用是让js无法读取cookie</span></span>
<span class="line"><span style="color: #e1e4e8">        });</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">        res.write(JSON.stringify(postData));</span></span>
<span class="line"><span style="color: #e1e4e8">        res.end();</span></span>
<span class="line"><span style="color: #e1e4e8">    });</span></span>
<span class="line"><span style="color: #e1e4e8">});</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">server.listen(&#39;8080&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8">console.log(&#39;Server is running at port 8080...&#39;);</span></span></code></pre></div></div></figure>

<h4 id="七、-nginx代理跨域"><a href="#七、-nginx代理跨域" class="headerlink" title="七、 nginx代理跨域"></a><strong>七、 nginx代理跨域</strong></h4><h5 id="1、-nginx配置解决iconfont跨域"><a href="#1、-nginx配置解决iconfont跨域" class="headerlink" title="1、 nginx配置解决iconfont跨域"></a><strong>1、 nginx配置解决iconfont跨域</strong></h5><p>浏览器跨域访问js、css、img等常规静态资源被同源策略许可，但iconfont字体文件(eot|otf|ttf|woff|svg)例外，此时可在nginx的静态资源服务器中加入以下配置。</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">location / {</span></span>
<span class="line"><span style="color: #e1e4e8">  add_header Access-Control-Allow-Origin *;</span></span>
<span class="line"><span style="color: #e1e4e8">}</span></span></code></pre></div></div></figure>

<h5 id="2、-nginx反向代理接口跨域"><a href="#2、-nginx反向代理接口跨域" class="headerlink" title="2、 nginx反向代理接口跨域"></a><strong>2、 nginx反向代理接口跨域</strong></h5><p>跨域原理： 同源策略是浏览器的安全策略，不是HTTP协议的一部分。服务器端调用HTTP接口只是使用HTTP协议，不会执行JS脚本，不需要同源策略，也就不存在跨越问题。</p>
<p>实现思路：通过nginx配置一个代理服务器（域名与domain1相同，端口不同）做跳板机，反向代理访问domain2接口，并且可以顺便修改cookie中domain信息，方便当前域cookie写入，实现跨域登录。</p>
<p>nginx具体配置：</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">#proxy服务器</span></span>
<span class="line"><span style="color: #e1e4e8">server {</span></span>
<span class="line"><span style="color: #e1e4e8">    listen       81;</span></span>
<span class="line"><span style="color: #e1e4e8">    server_name  www.domain1.com;</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">    location / {</span></span>
<span class="line"><span style="color: #e1e4e8">        proxy_pass   http://www.domain2.com:8080;  #反向代理</span></span>
<span class="line"><span style="color: #e1e4e8">        proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名</span></span>
<span class="line"><span style="color: #e1e4e8">        index  index.html index.htm;</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">        # 当用webpack-dev-server等中间件代理接口访问nignx时，此时无浏览器参与，故没有同源限制，下面的跨域配置可不启用</span></span>
<span class="line"><span style="color: #e1e4e8">        add_header Access-Control-Allow-Origin http://www.domain1.com;  #当前端只跨域不带cookie时，可为*</span></span>
<span class="line"><span style="color: #e1e4e8">        add_header Access-Control-Allow-Credentials true;</span></span>
<span class="line"><span style="color: #e1e4e8">    }</span></span>
<span class="line"><span style="color: #e1e4e8">}</span></span></code></pre></div></div></figure>

<p>1.) 前端代码示例：</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">var xhr = new XMLHttpRequest();</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">// 前端开关：浏览器是否读写cookie</span></span>
<span class="line"><span style="color: #e1e4e8">xhr.withCredentials = true;</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">// 访问nginx中的代理服务器</span></span>
<span class="line"><span style="color: #e1e4e8">xhr.open(&#39;get&#39;, &#39;http://www.domain1.com:81/?user=admin&#39;, true);</span></span>
<span class="line"><span style="color: #e1e4e8">xhr.send();</span></span></code></pre></div></div></figure>

<p>2.) Nodejs后台示例：</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">var http = require(&#39;http&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8">var server = http.createServer();</span></span>
<span class="line"><span style="color: #e1e4e8">var qs = require(&#39;querystring&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">server.on(&#39;request&#39;, function(req, res) {</span></span>
<span class="line"><span style="color: #e1e4e8">    var params = qs.parse(req.url.substring(2));</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">    // 向前台写cookie</span></span>
<span class="line"><span style="color: #e1e4e8">    res.writeHead(200, {</span></span>
<span class="line"><span style="color: #e1e4e8">        &#39;Set-Cookie&#39;: &#39;l=a123456;Path=/;Domain=www.domain2.com;HttpOnly&#39;   // HttpOnly:脚本无法读取</span></span>
<span class="line"><span style="color: #e1e4e8">    });</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">    res.write(JSON.stringify(params));</span></span>
<span class="line"><span style="color: #e1e4e8">    res.end();</span></span>
<span class="line"><span style="color: #e1e4e8">});</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">server.listen(&#39;8080&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8">console.log(&#39;Server is running at port 8080...&#39;);</span></span></code></pre></div></div></figure>

<h4 id="八、-Nodejs中间件代理跨域"><a href="#八、-Nodejs中间件代理跨域" class="headerlink" title="八、 Nodejs中间件代理跨域"></a><strong>八、 Nodejs中间件代理跨域</strong></h4><p>node中间件实现跨域代理，原理大致与nginx相同，都是通过启一个代理服务器，实现数据的转发，也可以通过设置cookieDomainRewrite参数修改响应头中cookie中域名，实现当前域的cookie写入，方便接口登录认证。</p>
<h5 id="1、-非vue框架的跨域（2次跨域）"><a href="#1、-非vue框架的跨域（2次跨域）" class="headerlink" title="1、 非vue框架的跨域（2次跨域）"></a><strong>1、 非vue框架的跨域（2次跨域）</strong></h5><p>利用node + express + http-proxy-middleware搭建一个proxy服务器。</p>
<p>1.）前端代码示例：</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">var xhr = new XMLHttpRequest();</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">// 前端开关：浏览器是否读写cookie</span></span>
<span class="line"><span style="color: #e1e4e8">xhr.withCredentials = true;</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">// 访问http-proxy-middleware代理服务器</span></span>
<span class="line"><span style="color: #e1e4e8">xhr.open(&#39;get&#39;, &#39;http://www.domain1.com:3000/login?user=admin&#39;, true);</span></span>
<span class="line"><span style="color: #e1e4e8">xhr.send();</span></span></code></pre></div></div></figure>

<p>2.）中间件服务器：</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">var express = require(&#39;express&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8">var proxy = require(&#39;http-proxy-middleware&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8">var app = express();</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">app.use(&#39;/&#39;, proxy({</span></span>
<span class="line"><span style="color: #e1e4e8">    // 代理跨域目标接口</span></span>
<span class="line"><span style="color: #e1e4e8">    target: &#39;http://www.domain2.com:8080&#39;,</span></span>
<span class="line"><span style="color: #e1e4e8">    changeOrigin: true,</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">    // 修改响应头信息，实现跨域并允许带cookie</span></span>
<span class="line"><span style="color: #e1e4e8">    onProxyRes: function(proxyRes, req, res) {</span></span>
<span class="line"><span style="color: #e1e4e8">        res.header(&#39;Access-Control-Allow-Origin&#39;, &#39;http://www.domain1.com&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8">        res.header(&#39;Access-Control-Allow-Credentials&#39;, &#39;true&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8">    },</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">    // 修改响应信息中的cookie域名</span></span>
<span class="line"><span style="color: #e1e4e8">    cookieDomainRewrite: &#39;www.domain1.com&#39;  // 可以为false，表示不修改</span></span>
<span class="line"><span style="color: #e1e4e8">}));</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">app.listen(3000);</span></span>
<span class="line"><span style="color: #e1e4e8">console.log(&#39;Proxy server is listen at port 3000...&#39;);</span></span></code></pre></div></div></figure>

<p>3.）Nodejs后台同（六：nginx）</p>
<h5 id="2、-vue框架的跨域（1次跨域）"><a href="#2、-vue框架的跨域（1次跨域）" class="headerlink" title="2、 vue框架的跨域（1次跨域）"></a><strong>2、 vue框架的跨域（1次跨域）</strong></h5><p>利用node + webpack + webpack-dev-server代理接口跨域。在开发环境下，由于vue渲染服务和接口代理服务都是webpack-dev-server同一个，所以页面与代理接口之间不再跨域，无须设置headers跨域信息了。</p>
<p>webpack.config.js部分配置：</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">module.exports = {</span></span>
<span class="line"><span style="color: #e1e4e8">    entry: {},</span></span>
<span class="line"><span style="color: #e1e4e8">    module: {},</span></span>
<span class="line"><span style="color: #e1e4e8">    ...</span></span>
<span class="line"><span style="color: #e1e4e8">    devServer: {</span></span>
<span class="line"><span style="color: #e1e4e8">        historyApiFallback: true,</span></span>
<span class="line"><span style="color: #e1e4e8">        proxy: [{</span></span>
<span class="line"><span style="color: #e1e4e8">            context: &#39;/login&#39;,</span></span>
<span class="line"><span style="color: #e1e4e8">            target: &#39;http://www.domain2.com:8080&#39;,  // 代理跨域目标接口</span></span>
<span class="line"><span style="color: #e1e4e8">            changeOrigin: true,</span></span>
<span class="line"><span style="color: #e1e4e8">            secure: false,  // 当代理某些https服务报错时用</span></span>
<span class="line"><span style="color: #e1e4e8">            cookieDomainRewrite: &#39;www.domain1.com&#39;  // 可以为false，表示不修改</span></span>
<span class="line"><span style="color: #e1e4e8">        }],</span></span>
<span class="line"><span style="color: #e1e4e8">        noInfo: true</span></span>
<span class="line"><span style="color: #e1e4e8">    }</span></span>
<span class="line"><span style="color: #e1e4e8">}</span></span></code></pre></div></div></figure>

<h4 id="九、-WebSocket协议跨域"><a href="#九、-WebSocket协议跨域" class="headerlink" title="九、 WebSocket协议跨域"></a>九、 WebSocket协议跨域</h4><p>WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信，同时允许跨域通讯，是server push技术的一种很好的实现。<br>原生WebSocket API使用起来不太方便，我们使用Socket.io，它很好地封装了webSocket接口，提供了更简单、灵活的接口，也对不支持webSocket的浏览器提供了向下兼容。</p>
<p>1.）前端代码：</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">&lt;div&gt;user input：&lt;input type=&quot;text&quot;&gt;&lt;/div&gt;</span></span>
<span class="line"><span style="color: #e1e4e8">&lt;script src=&quot;https://cdn.bootcss.com/socket.io/2.2.0/socket.io.js&quot;&gt;&lt;/script&gt;</span></span>
<span class="line"><span style="color: #e1e4e8">&lt;script&gt;</span></span>
<span class="line"><span style="color: #e1e4e8">var socket = io(&#39;http://www.domain2.com:8080&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">// 连接成功处理</span></span>
<span class="line"><span style="color: #e1e4e8">socket.on(&#39;connect&#39;, function() {</span></span>
<span class="line"><span style="color: #e1e4e8">    // 监听服务端消息</span></span>
<span class="line"><span style="color: #e1e4e8">    socket.on(&#39;message&#39;, function(msg) {</span></span>
<span class="line"><span style="color: #e1e4e8">        console.log(&#39;data from server: ---&gt; &#39; + msg); </span></span>
<span class="line"><span style="color: #e1e4e8">    });</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">    // 监听服务端关闭</span></span>
<span class="line"><span style="color: #e1e4e8">    socket.on(&#39;disconnect&#39;, function() { </span></span>
<span class="line"><span style="color: #e1e4e8">        console.log(&#39;Server socket has closed.&#39;); </span></span>
<span class="line"><span style="color: #e1e4e8">    });</span></span>
<span class="line"><span style="color: #e1e4e8">});</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">document.getElementsByTagName(&#39;input&#39;)[0].onblur = function() {</span></span>
<span class="line"><span style="color: #e1e4e8">    socket.send(this.value);</span></span>
<span class="line"><span style="color: #e1e4e8">};</span></span>
<span class="line"><span style="color: #e1e4e8">&lt;/script&gt;</span></span></code></pre></div></div></figure>

<p>2.）Nodejs socket后台：</p>
<figure class="shiki"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #e1e4e8">var http = require(&#39;http&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8">var socket = require(&#39;socket.io&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">// 启http服务</span></span>
<span class="line"><span style="color: #e1e4e8">var server = http.createServer(function(req, res) {</span></span>
<span class="line"><span style="color: #e1e4e8">    res.writeHead(200, {</span></span>
<span class="line"><span style="color: #e1e4e8">        &#39;Content-type&#39;: &#39;text/html&#39;</span></span>
<span class="line"><span style="color: #e1e4e8">    });</span></span>
<span class="line"><span style="color: #e1e4e8">    res.end();</span></span>
<span class="line"><span style="color: #e1e4e8">});</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">server.listen(&#39;8080&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8">console.log(&#39;Server is running at port 8080...&#39;);</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">// 监听socket连接</span></span>
<span class="line"><span style="color: #e1e4e8">socket.listen(server).on(&#39;connection&#39;, function(client) {</span></span>
<span class="line"><span style="color: #e1e4e8">    // 接收信息</span></span>
<span class="line"><span style="color: #e1e4e8">    client.on(&#39;message&#39;, function(msg) {</span></span>
<span class="line"><span style="color: #e1e4e8">        client.send(&#39;hello：&#39; + msg);</span></span>
<span class="line"><span style="color: #e1e4e8">        console.log(&#39;data from client: ---&gt; &#39; + msg);</span></span>
<span class="line"><span style="color: #e1e4e8">    });</span></span>
<span class="line"><span style="color: #e1e4e8"></span></span>
<span class="line"><span style="color: #e1e4e8">    // 断开处理</span></span>
<span class="line"><span style="color: #e1e4e8">    client.on(&#39;disconnect&#39;, function() {</span></span>
<span class="line"><span style="color: #e1e4e8">        console.log(&#39;Client socket has closed.&#39;); </span></span>
<span class="line"><span style="color: #e1e4e8">    });</span></span>
<span class="line"><span style="color: #e1e4e8">});</span></span></code></pre></div></div></figure>

<hr>
<p>参考文档:<a target="_blank" rel="noopener" href="https://segmentfault.com/a/1190000011145364">segmentfault平台文章:前端常见跨域解决方案</a></p>

    
  </article>

  
      
    <div class="nexmoe-post-copyright">
        <strong>本文作者：</strong>tangyuxian<br>
        
        <strong>本文链接：</strong><a href="https://www.tangyuxian.com/2021/03/19/%E5%89%8D%E7%AB%AF/%E6%B5%8F%E8%A7%88%E5%99%A8/%E6%B5%8F%E8%A7%88%E5%99%A8-%E8%B7%A8%E5%9F%9F%E5%8F%8A%E5%85%B6%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88/" title="https:&#x2F;&#x2F;www.tangyuxian.com&#x2F;2021&#x2F;03&#x2F;19&#x2F;%E5%89%8D%E7%AB%AF&#x2F;%E6%B5%8F%E8%A7%88%E5%99%A8&#x2F;%E6%B5%8F%E8%A7%88%E5%99%A8-%E8%B7%A8%E5%9F%9F%E5%8F%8A%E5%85%B6%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88&#x2F;" target="_blank" rel="noopener">https:&#x2F;&#x2F;www.tangyuxian.com&#x2F;2021&#x2F;03&#x2F;19&#x2F;%E5%89%8D%E7%AB%AF&#x2F;%E6%B5%8F%E8%A7%88%E5%99%A8&#x2F;%E6%B5%8F%E8%A7%88%E5%99%A8-%E8%B7%A8%E5%9F%9F%E5%8F%8A%E5%85%B6%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88&#x2F;</a><br>

        
            <strong>版权声明：</strong>本文采用 <a href="https://creativecommons.org/licenses/by-nc-sa/3.0/cn/deed.zh" target="_blank">CC BY-NC-SA 3.0 CN</a> 协议进行许可

        
    </div>


  
  
  <div class="nexmoe-post-meta nexmoe-rainbow">
   
    
        <a class="nexmoefont icon-tag-fill -none-link" href="/tags/%E6%B5%8F%E8%A7%88%E5%99%A8/" rel="tag">浏览器</a>
    
</div>
  
  
    <script async src="/js/copy-codeblock.js?v=1763992123963"></script>
  

  
      <div class="nexmoe-post-footer">
          <div class="valine"></div>
<script src='https://lib.baomitu.com/valine/1.3.9/Valine.min.js'></script>
<script>
  new Valine({
      el: '.valine',
      appId: 'r5zxC0st0DDjPA9auXzMV7HY-gzGzoHsz',
      appKey: '3bqCsovpyfTPHUzTHovd3V3V'
  })
</script>

      </div>
  
</div></div><div class="nexmoe-post-right">    <div class="nexmoe-fixed">
        <div class="nexmoe-tool">

            

            
            
            <button class="mdui-fab catalog" style="overflow:unset;">
                <i class="nexmoefont icon-i-catalog"></i>
                <div class="nexmoe-toc">
                    <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BB%80%E4%B9%88%E6%98%AF%E8%B7%A8%E5%9F%9F%EF%BC%9F"><span class="toc-number">1.</span> <span class="toc-text">什么是跨域？</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%B8%B8%E8%A7%81%E8%B7%A8%E5%9F%9F%E5%9C%BA%E6%99%AF"><span class="toc-number">2.</span> <span class="toc-text">常见跨域场景</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E8%B7%A8%E5%9F%9F%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88"><span class="toc-number">3.</span> <span class="toc-text">跨域解决方案</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%B8%80%E3%80%81-%E9%80%9A%E8%BF%87jsonp%E8%B7%A8%E5%9F%9F"><span class="toc-number">3.0.1.</span> <span class="toc-text">一、 通过jsonp跨域</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BA%8C%E3%80%81-document-domain-iframe%E8%B7%A8%E5%9F%9F"><span class="toc-number">3.0.2.</span> <span class="toc-text">二、 document.domain + iframe跨域</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%B8%89%E3%80%81-location-hash-iframe%E8%B7%A8%E5%9F%9F"><span class="toc-number">3.0.3.</span> <span class="toc-text">三、 location.hash + iframe跨域</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%9B%9B%E3%80%81-window-name-iframe%E8%B7%A8%E5%9F%9F"><span class="toc-number">3.0.4.</span> <span class="toc-text">四、 window.name + iframe跨域</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BA%94%E3%80%81-postMessage%E8%B7%A8%E5%9F%9F"><span class="toc-number">3.0.5.</span> <span class="toc-text">五、 postMessage跨域</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%85%AD%E3%80%81-%E8%B7%A8%E5%9F%9F%E8%B5%84%E6%BA%90%E5%85%B1%E4%BA%AB%EF%BC%88CORS%EF%BC%89"><span class="toc-number">3.0.6.</span> <span class="toc-text">六、 跨域资源共享（CORS）</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#1%E3%80%81-%E5%89%8D%E7%AB%AF%E8%AE%BE%E7%BD%AE%EF%BC%9A"><span class="toc-number">3.0.6.1.</span> <span class="toc-text">1、 前端设置：</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2%E3%80%81-%E6%9C%8D%E5%8A%A1%E7%AB%AF%E8%AE%BE%E7%BD%AE%EF%BC%9A"><span class="toc-number">3.0.6.2.</span> <span class="toc-text">2、 服务端设置：</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%B8%83%E3%80%81-nginx%E4%BB%A3%E7%90%86%E8%B7%A8%E5%9F%9F"><span class="toc-number">3.0.7.</span> <span class="toc-text">七、 nginx代理跨域</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#1%E3%80%81-nginx%E9%85%8D%E7%BD%AE%E8%A7%A3%E5%86%B3iconfont%E8%B7%A8%E5%9F%9F"><span class="toc-number">3.0.7.1.</span> <span class="toc-text">1、 nginx配置解决iconfont跨域</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2%E3%80%81-nginx%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86%E6%8E%A5%E5%8F%A3%E8%B7%A8%E5%9F%9F"><span class="toc-number">3.0.7.2.</span> <span class="toc-text">2、 nginx反向代理接口跨域</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%85%AB%E3%80%81-Nodejs%E4%B8%AD%E9%97%B4%E4%BB%B6%E4%BB%A3%E7%90%86%E8%B7%A8%E5%9F%9F"><span class="toc-number">3.0.8.</span> <span class="toc-text">八、 Nodejs中间件代理跨域</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#1%E3%80%81-%E9%9D%9Evue%E6%A1%86%E6%9E%B6%E7%9A%84%E8%B7%A8%E5%9F%9F%EF%BC%882%E6%AC%A1%E8%B7%A8%E5%9F%9F%EF%BC%89"><span class="toc-number">3.0.8.1.</span> <span class="toc-text">1、 非vue框架的跨域（2次跨域）</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2%E3%80%81-vue%E6%A1%86%E6%9E%B6%E7%9A%84%E8%B7%A8%E5%9F%9F%EF%BC%881%E6%AC%A1%E8%B7%A8%E5%9F%9F%EF%BC%89"><span class="toc-number">3.0.8.2.</span> <span class="toc-text">2、 vue框架的跨域（1次跨域）</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%B9%9D%E3%80%81-WebSocket%E5%8D%8F%E8%AE%AE%E8%B7%A8%E5%9F%9F"><span class="toc-number">3.0.9.</span> <span class="toc-text">九、 WebSocket协议跨域</span></a></li></ol></li></ol></li></ol>
                </div>
            </button>
            

            

            <a href="#nexmoe-content" class="backtop toc-link" aria-label="Back To Top" title="top"><button class="mdui-fab mdui-ripple"><i class="nexmoefont icon-caret-top"></i></button></a>
        </div>
    </div>
</div></div><div id="nexmoe-pendant"><div class="nexmoe-drawer mdui-drawer nexmoe-pd" id="drawer">
    
        
            <div class="nexmoe-pd-item">
                <div class="clock">
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="needle" id="hours"></div>
        <div class="needle" id="minutes"></div>
        <div class="needle" id="seconds"></div>
        <div class="clock_logo">

        </div>

    </div>
<script>
        // ----- Variable declaration

        var data = {
                dt: new Date(),
                hours: {
                        el: document.querySelector('#hours'),
                        val: 0 },

                minutes: {
                        el: document.querySelector('#minutes'),
                        val: 0 },

                seconds: {
                        el: document.querySelector('#seconds'),
                        val: 0 },

                renderTime: 1000 };


        // ----- Clock rendering logic

        updateTime = () => {
                let hour = data.dt.getHours();
                let minute = data.dt.getMinutes();
                let second = data.dt.getSeconds();

                data.hours.el.classList.add('moving');
                data.minutes.el.classList.add('moving');
                data.seconds.el.classList.add('moving');

                data.hours.val = hour == 0 && data.hours.val == 59 * 6 * 5 ? 360 : hour * 6 * 5;
                data.minutes.val = minute == 0 && data.minutes.val == 59 * 6 ? 360 : minute * 6;
                data.seconds.val = second == 0 && data.seconds.val == 59 * 6 ? 360 : second * 6;

                data.hours.el.style.transform = `translate(-50%, -75%) rotate(${data.hours.val}deg)`;
                data.minutes.el.style.transform = `translate(-50%, -75%) rotate(${data.minutes.val}deg)`;
                data.seconds.el.style.transform = `translate(-50%, -75%) rotate(${data.seconds.val}deg)`;

                data.dt.setSeconds(second + 1);
        };

        // ----- Clock execution

        setInterval(() => {
                updateTime();
        }, data.renderTime);

        updateTime();

        // ----- Events area

        data.seconds.el.addEventListener('transitionend', () => {
                data.hours.el.classList.remove('moving');
                data.minutes.el.classList.remove('moving');
                data.seconds.el.classList.remove('moving');

                // if (data.hours.val == 360) {
                //   data.hours.el.style.transform = 'translate(-50%, -75%) rotate(0deg)';
                // }

                if (data.minutes.val == 360) {
                        data.minutes.el.style.transform = 'translate(-50%, -75%) rotate(0deg)';
                }

                if (data.seconds.val == 360) {
                        data.seconds.el.style.transform = 'translate(-50%, -75%) rotate(0deg)';
                }
        });

</script>
<style>
    .clock {
        background-color: #ffffff;
        width: 70vw;
        height: 70vw;
        max-width: 70vh;
        max-height: 70vh;
        border: solid 2.8vw var(--color-primary);
        position: relative;
        overflow: hidden;
        border-radius: 50%;
        box-sizing: border-box;
        box-shadow: 0 1.4vw 2.8vw var(--color2);
        zoom:0.2
    }

    .memory {
        position: absolute;
        top: 50%;
        left: 50%;
        transform-origin: center;
    }

    .memory:nth-child(1) {
        background-color: var(--color-primary);
        width: 2%;
        height: 8%;
        transform: translate(-50%, -50%) rotate(0deg) translateY(-520%);
    }

    .memory:nth-child(2) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(6deg) translateY(-1461%);
    }

    .memory:nth-child(3) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(12deg) translateY(-1461%);
    }

    .memory:nth-child(4) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(18deg) translateY(-1461%);
    }

    .memory:nth-child(5) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(24deg) translateY(-1461%);
    }

    .memory:nth-child(6) {
        background-color: var(--color-primary);
        width: 2%;
        height: 8%;
        transform: translate(-50%, -50%) rotate(30deg) translateY(-520%);
    }

    .memory:nth-child(7) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(36deg) translateY(-1461%);
    }

    .memory:nth-child(8) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(42deg) translateY(-1461%);
    }

    .memory:nth-child(9) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(48deg) translateY(-1461%);
    }

    .memory:nth-child(10) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(54deg) translateY(-1461%);
    }

    .memory:nth-child(11) {
        background-color: var(--color-primary);
        width: 2%;
        height: 8%;
        transform: translate(-50%, -50%) rotate(60deg) translateY(-520%);
    }

    .memory:nth-child(12) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(66deg) translateY(-1461%);
    }

    .memory:nth-child(13) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(72deg) translateY(-1461%);
    }

    .memory:nth-child(14) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(78deg) translateY(-1461%);
    }

    .memory:nth-child(15) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(84deg) translateY(-1461%);
    }

    .memory:nth-child(16) {
        background-color: var(--color-primary);
        width: 2%;
        height: 8%;
        transform: translate(-50%, -50%) rotate(90deg) translateY(-520%);
    }

    .memory:nth-child(17) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(96deg) translateY(-1461%);
    }

    .memory:nth-child(18) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(102deg) translateY(-1461%);
    }

    .memory:nth-child(19) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(108deg) translateY(-1461%);
    }

    .memory:nth-child(20) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(114deg) translateY(-1461%);
    }

    .memory:nth-child(21) {
        background-color: var(--color-primary);
        width: 2%;
        height: 8%;
        transform: translate(-50%, -50%) rotate(120deg) translateY(-520%);
    }

    .memory:nth-child(22) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(126deg) translateY(-1461%);
    }

    .memory:nth-child(23) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(132deg) translateY(-1461%);
    }

    .memory:nth-child(24) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(138deg) translateY(-1461%);
    }

    .memory:nth-child(25) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(144deg) translateY(-1461%);
    }

    .memory:nth-child(26) {
        background-color: var(--color-primary);
        width: 2%;
        height: 8%;
        transform: translate(-50%, -50%) rotate(150deg) translateY(-520%);
    }

    .memory:nth-child(27) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(156deg) translateY(-1461%);
    }

    .memory:nth-child(28) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(162deg) translateY(-1461%);
    }

    .memory:nth-child(29) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(168deg) translateY(-1461%);
    }

    .memory:nth-child(30) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(174deg) translateY(-1461%);
    }

    .memory:nth-child(31) {
        background-color: var(--color-primary);
        width: 2%;
        height: 8%;
        transform: translate(-50%, -50%) rotate(180deg) translateY(-520%);
    }

    .memory:nth-child(32) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(186deg) translateY(-1461%);
    }

    .memory:nth-child(33) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(192deg) translateY(-1461%);
    }

    .memory:nth-child(34) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(198deg) translateY(-1461%);
    }

    .memory:nth-child(35) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(204deg) translateY(-1461%);
    }

    .memory:nth-child(36) {
        background-color: var(--color-primary);
        width: 2%;
        height: 8%;
        transform: translate(-50%, -50%) rotate(210deg) translateY(-520%);
    }

    .memory:nth-child(37) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(216deg) translateY(-1461%);
    }

    .memory:nth-child(38) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(222deg) translateY(-1461%);
    }

    .memory:nth-child(39) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(228deg) translateY(-1461%);
    }

    .memory:nth-child(40) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(234deg) translateY(-1461%);
    }

    .memory:nth-child(41) {
        background-color: var(--color-primary);
        width: 2%;
        height: 8%;
        transform: translate(-50%, -50%) rotate(240deg) translateY(-520%);
    }

    .memory:nth-child(42) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(246deg) translateY(-1461%);
    }

    .memory:nth-child(43) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(252deg) translateY(-1461%);
    }

    .memory:nth-child(44) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(258deg) translateY(-1461%);
    }

    .memory:nth-child(45) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(264deg) translateY(-1461%);
    }

    .memory:nth-child(46) {
        background-color: var(--color-primary);
        width: 2%;
        height: 8%;
        transform: translate(-50%, -50%) rotate(270deg) translateY(-520%);
    }

    .memory:nth-child(47) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(276deg) translateY(-1461%);
    }

    .memory:nth-child(48) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(282deg) translateY(-1461%);
    }

    .memory:nth-child(49) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(288deg) translateY(-1461%);
    }

    .memory:nth-child(50) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(294deg) translateY(-1461%);
    }

    .memory:nth-child(51) {
        background-color: var(--color-primary);
        width: 2%;
        height: 8%;
        transform: translate(-50%, -50%) rotate(300deg) translateY(-520%);
    }

    .memory:nth-child(52) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(306deg) translateY(-1461%);
    }

    .memory:nth-child(53) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(312deg) translateY(-1461%);
    }

    .memory:nth-child(54) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(318deg) translateY(-1461%);
    }

    .memory:nth-child(55) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(324deg) translateY(-1461%);
    }

    .memory:nth-child(56) {
        background-color: var(--color-primary);
        width: 2%;
        height: 8%;
        transform: translate(-50%, -50%) rotate(330deg) translateY(-520%);
    }

    .memory:nth-child(57) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(336deg) translateY(-1461%);
    }

    .memory:nth-child(58) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(342deg) translateY(-1461%);
    }

    .memory:nth-child(59) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(348deg) translateY(-1461%);
    }

    .memory:nth-child(60) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(354deg) translateY(-1461%);
    }

    .needle {
        position: absolute;
        top: 50%;
        left: 50%;
        transform-origin: center;
    }

    .needle#hours {
        background-color: #1f1f1f;
        width: 4%;
        height: 30%;
        transform-origin: center 75%;
        transform: translate(-50%, -75%);
    }

    .needle#hours.moving {
        transition: transform 150ms ease-out;
    }

    .needle#hours:after {
        content: '';
        background-color: #1f1f1f;
        width: 4vw;
        height: 4vw;
        max-width: 4vh;
        max-height: 4vh;
        display: block;
        position: absolute;
        top: 75%;
        left: 50%;
        box-sizing: border-box;
        border-radius: 50%;
        transform: translate(-50%, -50%);
    }

    .needle#minutes {
        background-color: #1f1f1f;
        width: 2%;
        height: 45%;
        transform-origin: center 75%;
        transform: translate(-50%, -75%);
    }

    .needle#minutes.moving {
        transition: transform 150ms ease-out;
    }

    .needle#minutes:after {
        content: '';
        background-color: #1f1f1f;
        width: 4vw;
        height: 4vw;
        max-width: 4vh;
        max-height: 4vh;
        display: block;
        position: absolute;
        top: 75%;
        left: 50%;
        box-sizing: border-box;
        border-radius: 50%;
        transform: translate(-50%, -50%);
    }

    .needle#seconds {
        background-color: #cb2f2f;
        width: 1%;
        height: 50%;
        transform-origin: center 75%;
        transform: translate(-50%, -75%);
    }

    .needle#seconds.moving {
        transition: transform 150ms ease-out;
    }

    .needle#seconds:after {
        content: '';
        background-color: #cb2f2f;
        width: 2.5vw;
        height: 2.5vw;
        max-width: 2.5vh;
        max-height: 2.5vh;
        display: block;
        position: absolute;
        top: 75%;
        left: 50%;
        box-sizing: border-box;
        border-radius: 50%;
        transform: translate(-50%, -50%);
    }
    .clock_logo{
        width: 10vw;
        height: 10vw;
        max-width: 10vh;
        max-height: 10vh;
        position: absolute;
        top: 50%;
        left: 50%;
        box-sizing: border-box;
        border-radius: 50%;
        transform: translate(-50%, -50%);
        background-size: 100% 100%;
        background-repeat: no-repeat;
    }
    .clock_logo{
            width: 10vw;
            height: 10vw;
            max-width: 10vh;
            max-height: 10vh;
            position: absolute;
            top: 50%;
            left: 50%;
            box-sizing: border-box;
            border-radius: 50%;
            transform: translate(-50%, -50%);
            background-image: var(--clock-logo);
            background-size: 100% 100%;
            background-repeat: no-repeat;
    }
    @media (min-width: 100vh) {
        .clock {
            border: solid 2.8vh var(--color-primary);
            box-shadow: 0 1.4vh 2.8vh var(--color2);
        }
    }

</style>





            </div>
        
            <div class="nexmoe-pd-item">
                <div class="qweather" >
    <div id="he-plugin-standard">
        <iframe allowtransparency="true" frameborder="0" width="304" height="96" scrolling="no" src="//tianqi.2345.com/plugin/widget/index.htm?s=2&z=1&t=0&v=0&d=2&bd=0&k=000000&f=ff8040&ltf=009944&htf=cc0000&q=1&e=1&a=1&c=54511&w=300&h=96&align=center"></iframe>
    </div>
    <div class="qweather-logo">

    </div>
</div>
<style>
    .qweather{
        position: relative;
        padding-right: 5px;
    }
    .qweather #he-plugin-standard {
        border: 2px solid var(--color-primary);
        box-shadow: 0 1px 0 0 var(--color-primary), 0 1px 2px 0 var(--color-primary);
        border-radius: 8px;
        width: 300px;
        overflow: hidden;
    }
    .qweather-logo{
        position: absolute;
        right: 0;
        top: -15px;
        width: 40px;
        height: 40px;
        background-image: var(--qweather-logo);
        background-size: 100% 100%;
        background-repeat: no-repeat;
    }
</style>

            </div>
        
    
</div>
<style>
    .nexmoe-pd {
        left: auto;
        top: 40px;
        right: 0;
    }
    .nexmoe-pd-item{
       display: flex;
        justify-content: center;
        margin-bottom: 30px;
    }
    #nexmoe-pendant .mdui-drawer{
        width: 305px;
    }
    @media screen and (max-width: 1600px) {
        #nexmoe-pendant {
            display: none
        }
    }
</style>
</div><div id="nexmoe-footer"><!--!--></div><div id="nexmoe-search-space"><div class="search-container"><div class="search-header"><div class="search-input-container"><input class="search-input" type="text" placeholder="搜索" onInput="sinput();"></div><a class="search-close" onclick="sclose();">×</a></div><div class="search-body"></div></div></div><div></div><!-- hexo injector body_end start -->
<script src="https://cdn.jsdelivr.net/npm/hexo-shiki-plugin@latest/lib/codeblock.js"></script>

  <script>
  const CODE_CONFIG = {
    beautify: true,
    highlightCopy: true,
    highlightLang: true,
    highlightHeightLimit: null,
    isHighlightShrink: false,
    copy: {
      success: 'Copy Success',
      error: 'Copy Error',
      noSupport: 'Browser Not Support',
    }
  };
  console.log(
    `%c hexo-shiki-plugin %c v1.0.27 %c https://github.com/nova1751/hexo-shiki-plugin`,
    "color: #fff; background: #5f5f5f",
    "color: #fff; background: #80c8f8",
    ""
  );
  </script>
  <!-- hexo injector body_end end --><script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"model":{"jsonPath":"/live2dw/assets/xiaomai.model.json"},"display":{"position":"left","width":200,"height":500},"mobile":{"show":false},"react":{"opacity":0.9},"log":false,"pluginJsPath":"lib/","pluginModelPath":"assets/","pluginRootPath":"live2dw/","tagMode":false});</script></body></html>